package me.linczh.bank.action;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

import me.linczh.bank.bean.AccountBean;
import me.linczh.bank.bean.EmployeeBean;
import me.linczh.bank.bean.LogBean;
import me.linczh.bank.bean.OperatorBean;
import me.linczh.bank.bean.enums.AccountType;
import me.linczh.bank.bean.enums.DepositType;
import me.linczh.bank.bean.enums.Operation;
import me.linczh.bank.bean.enums.ResultType;
import me.linczh.bank.service.AccountService;
import me.linczh.bank.service.LogService;
import me.linczh.bank.service.OperatorService;
import me.linczh.framework.action.ActionExecutor;

public class AccountAction extends ActionExecutor {
	private String account;
	private String username;
	private String password;
	private String confirm;
	private String identity;
	private String balance;
	private String accounttype;
	private String deposittype;
	private String toaccount;
	private String tousername;
	private String newpassword;
	private String starttime;
	private String endtime;
	private String querytype;
	
	private AccountBean accountBean;
	private List<LogBean> accountLog;
	private ResultType result;
	
	public String create() {
		AccountService accountService = new AccountService();
		double b = 0;
		try {
			b = Double.parseDouble(balance);
			AccountType atype = AccountType.valueOf(accounttype);
			DepositType dtype = DepositType.valueOf(deposittype);
			accountBean = accountService.create(identity, username, password, b, atype, dtype);
			if (accountBean == null) result = ResultType.INSUFFICIENT_BALANCE;
			else result = ResultType.SUCCESS;
		} catch(NumberFormatException e) {
			result = ResultType.INVALID_INPUT_FORMAT;
		} catch (IllegalArgumentException e) {
			result = ResultType.INVALID_INPUT_ENUM;
		}
		
		if (result == ResultType.SUCCESS) {
			LogService logger = new LogService();
			logger.log(Operation.CREATE, accountBean, null, b, (EmployeeBean)super.session.getAttribute("user"));
		}
		return "success";
	}
	
	public String deposit() {
		AccountService accountService = new AccountService();
		OperatorService operatorService = new OperatorService();
		OperatorBean operatorBean = null;
		double b = 0;
		try {
			b = Double.parseDouble(balance);
			accountBean = accountService.getAccountByIdAndPassword(account, password);
			if (accountBean == null) {
				operatorBean = operatorService.getOperatorByAccountAndPassword(account, password);
				if (operatorBean != null) accountBean = accountService.getAccountByOperator(operatorBean);
			}
			if (accountBean == null) {
				result = ResultType.INVALID_ACCOUNT_OR_PWD;
			} else {
				accountService.deposit(accountBean, b);
				result = ResultType.SUCCESS;
			}
		} catch (NumberFormatException e) {
			result = ResultType.INVALID_INPUT_FORMAT;
		}
		
		if (result == ResultType.SUCCESS) {
			LogService logger = new LogService();
			logger.log(Operation.DEPOSIT, accountBean, operatorBean, b, (EmployeeBean)super.session.getAttribute("user"));
		}
		return "success";
	}
	
	public String withdrawal() {
		AccountService accountService = new AccountService();
		OperatorService operatorService = new OperatorService();
		OperatorBean operatorBean = null;
		double b = 0;
		try {
			b = Double.parseDouble(balance);
			accountBean = accountService.getAccountByIdAndPassword(account, password);
			if (accountBean == null) {
				operatorBean = operatorService.getOperatorByAccountAndPassword(account, password);
				if (operatorBean != null) accountBean = accountService.getAccountByOperator(operatorBean);
			}
			if (accountBean == null) {
				result = ResultType.INVALID_ACCOUNT_OR_PWD;
			} else if (!accountService.withdrawal(accountBean, b)) {
				result = ResultType.INSUFFICIENT_BALANCE;
			} else result = ResultType.SUCCESS;
		} catch (NumberFormatException e) {
			result = ResultType.INVALID_INPUT_FORMAT;
		}
		
		if (result == ResultType.SUCCESS) {
			LogService logger = new LogService();
			logger.log(Operation.WITHDRAWAL, accountBean, operatorBean, b, (EmployeeBean)super.session.getAttribute("user"));
		}
		return "success";
	}
	
	public String query() {
		AccountService accountService = new AccountService();
		OperatorService operatorService = new OperatorService();
		OperatorBean operatorBean = null;
		
		accountBean = accountService.getAccountByIdAndPassword(account, password);
		if (accountBean == null) {
			operatorBean = operatorService.getOperatorByAccountAndPassword(account, password);
			if (operatorBean != null) accountBean = accountService.getAccountByOperator(operatorBean);
		}
		if (accountBean == null) {
			result = ResultType.INVALID_ACCOUNT_OR_PWD;
		} else {
			if (accountBean.getIdentity().equals(identity)) {
				try {
					int type = Integer.parseInt(querytype);
					if (type == 1) {	// query log
						SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd");
						Date start = fmt.parse(starttime);
						Date end = fmt.parse(endtime);
						LogService logger = new LogService();
						accountLog = logger.accountLog(accountBean, start, end);
					}
					result = ResultType.SUCCESS;
				} catch (NumberFormatException e) {
					result = ResultType.INVALID_INPUT_FORMAT;
				} catch (ParseException e) {
					result = ResultType.INVALID_DATE_FORMAT;
				}
			} else result = ResultType.INVALID_ACCOUNT_OR_PWD;
		}
		
		if (result == ResultType.SUCCESS) {
			LogService logger = new LogService();
			logger.log(Operation.QUERY, accountBean, operatorBean, 0, (EmployeeBean)super.session.getAttribute("user"));
		}
		return "success";
	}
	
	public String transfer() {
		AccountService accountService = new AccountService();
		OperatorService operatorService = new OperatorService();
		OperatorBean operatorBean = null;
		double b = 0;
		AccountBean toAccount = null;
		try {
			b = Double.parseDouble(balance);
			accountBean = accountService.getAccountByIdAndPassword(account, password);
			if (accountBean == null) {
				operatorBean = operatorService.getOperatorByAccountAndPassword(account, password);
				if (operatorBean != null) accountBean = accountService.getAccountByOperator(operatorBean);
			}
			if (accountBean == null) {
				result = ResultType.INVALID_SRC_ACCOUNT_OR_PWD;
			} else if (!accountBean.getUsername().equals(username)) {
				result = ResultType.INVALID_CUSTOMER_INFO;
			} else {
				toAccount = accountService.getAccountById(toaccount);
				if (toAccount == null) result = ResultType.INVALID_DES_ACCOUNT_OR_PWD;
				else if (!toAccount.getUsername().equals(tousername)) result = ResultType.INVALID_CUSTOMER_INFO;
				else result = accountService.transfer(accountBean, toAccount, b);
			}
		} catch (NumberFormatException e) {
			result = ResultType.INVALID_INPUT_FORMAT;
		}
		
		if (result == ResultType.SUCCESS) {
			LogService logger = new LogService();
			logger.log(Operation.TRANSFER_OUT, accountBean, operatorBean, b, (EmployeeBean)super.session.getAttribute("user"));
			logger.log(Operation.TRANSFER_IN, toAccount, null, b, (EmployeeBean)super.session.getAttribute("user"));
		}
		return "success";
	}
	
	public String password() {
		AccountService accountService = new AccountService();
		accountBean = accountService.getAccountByIdAndPassword(account, password);
		if (accountBean == null) result = ResultType.INVALID_ACCOUNT_OR_PWD;
		else {
			accountBean = accountService.changePassword(accountBean, newpassword);
			if (accountBean == null) result = ResultType.FAIL_TO_UPDATE;
			else result = ResultType.SUCCESS;
		}
		
		if (result == ResultType.SUCCESS) {
			LogService logger = new LogService();
			logger.log(Operation.PASSWORD, accountBean, null, 0, (EmployeeBean)super.session.getAttribute("user"));
		}
		return "success";
	}
	
	public String delete() {
		AccountService accountService = new AccountService();
		accountBean = accountService.getAccountByIdAndPassword(account, password);
		if (accountBean == null) result = ResultType.INVALID_ACCOUNT_OR_PWD;
		else {
			if (!accountBean.getIdentity().equals(identity)) result = ResultType.INVALID_CUSTOMER_INFO;
			else if (!accountService.deleteAccount(accountBean)) result = ResultType.FAIL_TO_DELETE;
			else result = ResultType.SUCCESS;
		}

		if (result == ResultType.SUCCESS) {
			LogService logger = new LogService();
			logger.log(Operation.DELETE, accountBean, null, 0, (EmployeeBean)super.session.getAttribute("user"));
		}
		return "success";
	}
	
	public String getAccount() {
		return account;
	}
	public void setAccount(String account) {
		this.account = account;
	}
	public String getUsername() {
		return username;
	}
	public void setUsername(String username) {
		this.username = username;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	public String getConfirm() {
		return confirm;
	}
	public void setConfirm(String confirm) {
		this.confirm = confirm;
	}
	public String getIdentity() {
		return identity;
	}
	public void setIdentity(String identity) {
		this.identity = identity;
	}
	public String getBalance() {
		return balance;
	}
	public void setBalance(String balance) {
		this.balance = balance;
	}
	public String getAccounttype() {
		return accounttype;
	}
	public void setAccounttype(String accounttype) {
		this.accounttype = accounttype;
	}
	public String getDeposittype() {
		return deposittype;
	}
	public void setDeposittype(String deposittype) {
		this.deposittype = deposittype;
	}
	public AccountBean getAccountBean() {
		return accountBean;
	}
	public void setAccountBean(AccountBean accountBean) {
		this.accountBean = accountBean;
	}
	public ResultType getResult() {
		return result;
	}
	public void setResult(ResultType result) {
		this.result = result;
	}
	public String getToaccount() {
		return toaccount;
	}
	public void setToaccount(String toaccount) {
		this.toaccount = toaccount;
	}
	public String getTousername() {
		return tousername;
	}
	public void setTousername(String tousername) {
		this.tousername = tousername;
	}
	public String getNewpassword() {
		return newpassword;
	}
	public void setNewpassword(String newpassword) {
		this.newpassword = newpassword;
	}
	public String getStarttime() {
		return starttime;
	}
	public void setStarttime(String starttime) {
		this.starttime = starttime;
	}
	public String getEndtime() {
		return endtime;
	}
	public void setEndtime(String endtime) {
		this.endtime = endtime;
	}
	public String getQuerytype() {
		return querytype;
	}
	public void setQuerytype(String querytype) {
		this.querytype = querytype;
	}

	public List<LogBean> getAccountLog() {
		return accountLog;
	}

	public void setAccountLog(List<LogBean> accountLog) {
		this.accountLog = accountLog;
	}

}
